﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.Objects;
using System.Data.Common;
using System.ServiceModel;

namespace Fdd.Aspen.Infrastructure.Data
{
    public class WcfObjectContextAdapter : IObjectContext
    {
        public IObjectSet<T> CreateObjectSet<T>() where T : class
        {
            return Context.CreateObjectSet<T>();
        }


        public void SaveChanges()
        {
            Context.SaveChanges();
        }


        public void Dispose()
        {
            Context.Dispose();
        }


        public WcfObjectContextAdapter(IObjectContextFactory objectContextFactory)
        {
            if (objectContextFactory == null)
                throw new ArgumentNullException("sessionFactory");

            if (Context == null)
                Context = objectContextFactory.Create();
        }


        public ObjectContext Context
        {
            get
            {
                if (WcfOperationContainerExtension.Current == null)
                    return null;

                return WcfOperationContainerExtension.Current.Context;
            }
            set
            {
                if (CurrentOperationContext == null)
                    return;

                CurrentOperationContext.Extensions.Add(new WcfOperationContainerExtension(value));
                CurrentOperationContext.OperationCompleted += CurrentOperationContext_OperationCompleted;
            }
        }


        private void CurrentOperationContext_OperationCompleted(object sender, EventArgs e)
        {
            var context = WcfOperationContainerExtension.Current.Context;
            context.Dispose();
        }


        private OperationContext CurrentOperationContext
        {
            get { return OperationContext.Current; }
        }


        private class WcfOperationContainerExtension : IExtension<OperationContext>
        {
            public ObjectContext Context { get; set; }

            public WcfOperationContainerExtension(ObjectContext context)
            {
                Context = context;
            }

            public void Attach(OperationContext owner) { }
            public void Detach(OperationContext owner) { }

            public static WcfOperationContainerExtension Current
            {
                get
                {
                    if (OperationContext.Current == null)
                        return null;

                    return OperationContext.Current.Extensions.Find<WcfOperationContainerExtension>();
                }
            }
        }
    }
}
